package com.herui.sdyu_lib.blu.utils;

import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothSocket;
import android.util.Log;


import com.herui.sdyu_lib.blu.BlueDevice;
import com.herui.sdyu_lib.blu.BluDeviceConfig;
import com.herui.sdyu_lib.utils.LogUtils;
import com.herui.sdyu_lib.utils.ToastUtil;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.UUID;



/**
 * Created by amanda.shan on 2017/8/16.
 */

public class BluService implements BAction, Runnable {

    private static final UUID SerialPortServiceClass_UUID = UUID
            .fromString("00001101-0000-1000-8000-00805F9B34FB");

    private int mostWaitTime = 60 * 1000;

    private BlueDevice mBlueDevice;
    protected BluetoothAdapter mBluetoothAdapter;

    private BluetoothSocket mmSocket;
    private InputStream mmInStream = null;
    private OutputStream mmOutStream;

    private ConnectThread connectThread;

    private Blis blis;
    private boolean isRunning;
    private byte[] readBytes = new byte[1000];
    private Thread comBluDeviceThread;

    public BluService(Blis blis, BluetoothAdapter bluetoothAdapter) {
        this.blis = blis;
        mBluetoothAdapter = bluetoothAdapter;
    }

    @Override
    public void send(byte[] bytes) {
        send(bytes, bytes.length);
    }

    @Override
    public void send(byte[] bytes, int len) {
        try {
            if (mmOutStream != null)
                mmOutStream.write(bytes, 0, len);
        } catch (IOException e) {
            e.printStackTrace();

            LogUtils.e("蓝牙2.0发送异常");
            disConnect();
            blis.bluConenctState(BluDeviceConfig.NOTCONNECT);
        }

    }

    @Override
    public void setBlis(Blis blis) {
        this.blis = blis;
    }

    @Override
    public void connect(BlueDevice blueDevice) {
        mBlueDevice = blueDevice;
        connectThread = new ConnectThread(mBlueDevice.getBlueMac());
        connectThread.start();
    }

    @Override
    public void disConnect() {
        cancellAllConnect();
    }

    @Override
    public void setMostWaitTime(int mostWaitTime) {
        this.mostWaitTime = mostWaitTime;
    }

    /**
     * 关闭所有
     */
    private void cancellAllConnect() {
        if (connectThread != null) {
            connectThread.cancel();
        }
        if (comBluDeviceThread != null)
            isRunning = false;
        comBluDeviceThread = null;

        if (mmSocket != null) {
            try {
                mmSocket.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    private void connectedAction() {
        comBluDeviceThread = new Thread(this);
        comBluDeviceThread.start();

        blis.bluConenctState(BluDeviceConfig.ISCONNECT);

    }

    @Override
    public void run() {
        int temp = 0;
        try {
            isRunning = true;
            while (isRunning) {

                if (mmInStream.available() <= 0) {
                    Thread.sleep(5);
                    temp += 5;

                    if (temp >= mostWaitTime) {
                        LogUtils.i(temp + "");
                        LogUtils.e("超时等待接收数据");
                        ToastUtil.showMessage("蓝牙数据接收超时");

                        disConnect();
                        blis.bluConenctState(BluDeviceConfig.NOTCONNECT);
                        break;
                    }
                } else {
                    temp = 0;
                    int len = mmInStream.read(readBytes);

                    if (len > 0) {
                        blis.reciveBlu(readBytes, len);
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            isRunning = false;
        }
    }

    /**
     * 连接蓝牙的线程
     *
     * @author Administrator
     */
    private class ConnectThread extends Thread {
        private BluetoothDevice mmDevice;

        private String address;
        private boolean isRun;

        public ConnectThread(String address) {
            this.address = address;
        }

        public void run() {
            if (address != null)
                LogUtils.i("start connect " + address);
            if (blis != null) {
                blis.bluConenctState(BluDeviceConfig.CONNECTING);
            }

            int reConnectTimes = 3;
            isRun = true;
            while (isRun && reConnectTimes > 0) {
                try {
                    mmDevice = mBluetoothAdapter.getRemoteDevice(address);
                    mmSocket = mmDevice
                            .createRfcommSocketToServiceRecord(SerialPortServiceClass_UUID);
                    if (mmSocket != null)
                        mmSocket.connect();

                    try {
                        mmInStream = mmSocket.getInputStream();
                        mmOutStream = mmSocket.getOutputStream();
                    } catch (IOException e) {
                        Log.e("BluService", "蓝牙2.0获取输入输出 IO 失败", e);

                        LogUtils.e("蓝牙2.0发送异常");
                        blis.bluConenctState(BluDeviceConfig.NOTCONNECT);
                        return;
                    }
                    connectedAction();
                    break;
                } catch (IOException e) {

                    reConnectTimes--;
                    if (reConnectTimes > 0) {
                        LogUtils.i("reConnectTimes = " + reConnectTimes);
                        continue;
                    }

                    LogUtils.e("蓝牙2.0连接失败");
                    if (blis != null) {
                        blis.bluConenctState(BluDeviceConfig.NOTCONNECT);
                    }
                    try {
                        if (mmSocket != null)
                            mmSocket.close();
                    } catch (IOException e2) {
                        LogUtils.i("unable to close() socket during connection failure");
                    }
                }
            }

            synchronized (BluService.this) {
                connectThread = null;
            }
        }

        public synchronized void cancel() {
            LogUtils.i("cancel connect socket");
            isRun = false;
            try {
                if (mmSocket != null)
                    mmSocket.close();
            } catch (IOException e) {
                LogUtils.i("close() of connect socket failed", e);
            }
            try {
                this.join();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

}
